#ifndef RESULT_STR_H
#define RESULT_STR_H

#include "prot.h"
#include "paging_api.h"

#ifdef __KERNEL__
#define RSPRINT(...) printk("<1>" __VA_ARGS__)
#else
#include <stdio.h>
#define RSPRINT(...) printf(__VA_ARGS__)
#endif


int sprintPFEC(char *str, unsigned err_code) {
  str[0] = (err_code & PF_INSTRUCTION ? 'I' : '_');
  str[1] = (err_code & PF_RCVD        ? 'R' : '_');
  str[2] = (err_code & PF_USER        ? 'U' : '_');
  str[3] = (err_code & PF_WRITE       ? 'W' : '_');
  str[4] = (err_code & PF_PRESENT     ? 'P' : '_');
  str[5] = ' ';
  str[6] = 0;
  
  return 6;
}

void errcodeToString(struct interrupt_info *info, char *str) {
  if (info->has_error_code) {
    if (info->int_num == 14)
      str += sprintPFEC(str, info->error_code);
      
    sprintf(str, "(0x%x)", info->error_code);
  }
  else {
    sprintf(str, "no err. code (0x%x)", info->error_code);
  }
}

void intnumToString(unsigned int_num, char *str) {
  if (int_num == 14)
    sprintf(str, "#PF");
  else
    sprintf(str, "#%u", int_num);
}

void print_int_info (struct interrupt_info *info) {
  char intnum_s[10];
  char errcode_s[50];
  
  if (info->interrupt) {
    intnumToString (info->int_num, intnum_s);
    errcodeToString (info, errcode_s);
    
    RSPRINT ("%s %s\n", intnum_s, errcode_s);
  }
  else {
    RSPRINT ("no interrupts\n");
  }
}


int rs_max_name = 20;
void print_header(void)
{
  RSPRINT ("%-*s  %s  %s\n",
       rs_max_name,
       "test",
       "interrupt",
       "err code"
      );
}

void print_row (char *name, struct interrupt_info *info) {
  char intnum_s[10];
  char errcode_s[50];
  
  if (info->interrupt) {
    intnumToString (info->int_num, intnum_s);
    errcodeToString (info, errcode_s);
    
    RSPRINT ("%-*s  %9s  %s\n", rs_max_name, name, intnum_s, errcode_s);
  }
  else {
    RSPRINT ("%-*s  no interrupts\n", rs_max_name, name);
  }
}


void print_row_n (int row, struct interrupt_info *info) {
  char name[20];
  sprintf (name, "%d", row);
  
  print_row (name, info);
}


void _setMaxName (int max_name) {
  if (max_name != 0)
    rs_max_name = max_name;
  
  if (rs_max_name < 4)
    rs_max_name = 4;
}


void print_table (struct interrupt_info *begin, struct interrupt_info *end, char *names[], int max_name)
{
  struct interrupt_info *info;
  
  _setMaxName (max_name);
  
  print_header();
  
  for (info = begin; info != end; ++info) {
    for ( ; (*names)[0] == '@'; ++names)
      RSPRINT("\n%s\n", *names);
    
    print_row (*names++, info);
  }
}

void print_table_n (struct interrupt_info *begin, struct interrupt_info *end, int max_name)
{
  struct interrupt_info *info;
  
  _setMaxName (max_name);
  
  print_header();
  
  for (info = begin; info != end; ++info) {
    print_row_n (info - begin, info);
  }
}


#endif /* RESULT_STR_H */